package com.huan.hystrix.hystrix;

import com.huan.hystrix.entity.Product;
import com.huan.hystrix.service.ProductService;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import lombok.extern.slf4j.Slf4j;

/**
 * 查询商品 command
 * <p>
 * 信号量隔离
 *
 * @author huan.fu
 * @date 2018/8/8 - 17:49
 */
@Slf4j
public class NewSelectProductCommand extends HystrixCommand<Product> {

	private ProductService productService;
	private String productId;

	public NewSelectProductCommand(ProductService productService, String productId) {
		super(
				HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("DefaultGroup"))
						.andCommandKey(HystrixCommandKey.Factory.asKey("NewMethodName(args)"))
						.andCommandPropertiesDefaults(
								HystrixCommandProperties.Setter()
										.withExecutionTimeoutEnabled(true)
										// 超时时间为 10s
										.withExecutionTimeoutInMilliseconds(10000)
										// 使用线程池进行隔离
										.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
										// 同时并发执行的数量，当超过时将直接拒绝
										.withExecutionIsolationSemaphoreMaxConcurrentRequests(100)
										.withFallbackIsolationSemaphoreMaxConcurrentRequests(1000)
						)
		);

		this.productService = productService;
		this.productId = productId;
	}

	@Override
	protected Product run() throws Exception {
		log.info("----> Thread Name:{}", Thread.currentThread().getName());
		return productService.selectOne(productId);
	}

	@Override
	protected Product getFallback() {
		return Product.builder().productName("服务降级:" + getExecutionException().toString()).build();
	}
}